
#include<head.h>
 
#define PORT 8824 // 服务器监听的端口号
#define BUFFER_SIZE 1024 // 用于接收和发送消息的缓冲区大小
#define NAME_SIZE 20 // 用户名称的最大长度

// 函数：接收消息的线程函数
void *receive_messages(void *socketfd_p)
{
    int sockfd = *((int *)socketfd_p); // 获取套接字文件描述符
    char buffer[BUFFER_SIZE];          // 用于存储接收到的消息
    int len;                           // 接收消息的长度
    // 循环接收消息直到连接关闭
    while ((len = recv(sockfd, buffer, BUFFER_SIZE, 0)) > 0)
    {
        buffer[len] = '\0';     // 添加字符串终止符
        printf("%s\n", buffer); // 在控制台打印接收到的消息
    }
    pthread_exit(NULL); // 退出线程
}

int main(void)
{
    int socketfd;            // 套接字文件描述符
    struct sockaddr_in addr; // 地址结构
    pthread_t recv_thread;   // 接收消息的线程
    char buf[BUFFER_SIZE];   // 用于存储用户输入的消息
    char name[NAME_SIZE];    // 用户的名称

    char *tips = "请输入名字,长度不超过5:\n";        // 提示用户输入名称的消息
    fwrite(tips, sizeof(char), strlen(tips), stdout); // 将提示消息写入标准输出

    fgets(name, NAME_SIZE, stdin); // 从标准输入获取用户输入的名称

    name[strlen(name) - 1] = '\0'; // 去除名称末尾的换行符

    printf("name: %s\n", name); // 在控制台打印用户的名称

    if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {                                      // 创建套接字
        perror("Failed to create socket"); // 打印错误信息
        exit(EXIT_FAILURE);                // 退出程序
    }

    addr.sin_port = htons(PORT); // 设置端口号
    addr.sin_family = AF_INET;   // 设置地址族为IPv4

    // 将IP地址从文本格式转换为二进制格式
    if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr) <= 0)
    {
        perror("Invalid address/Address not supported"); // 打印错误信息
        exit(EXIT_FAILURE);                              // 退出程序
    }

    // 连接到服务器
    if (connect(socketfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("Connection Failed"); // 打印错误信息
        exit(EXIT_FAILURE);          // 退出程序
    }

    // 创建线程用于接收消息
    pthread_create(&recv_thread, NULL, receive_messages, &socketfd); 

    // 发送用户名到服务器
    send(socketfd, name, strlen(name), 0);

    // 循环获取用户输入并发送消息到服务器
    while (1)
    {
        fgets(buf, BUFFER_SIZE, stdin);      // 从标准输入获取用户输入的消息                         // 读取并丢弃换行符
        if (strcmp(buf, "quit\n") == 0)     // 如果用户输入的是"exit"，则退出循环
            break;                          // 退出循环
        send(socketfd, buf, strlen(buf), 0); // 发送消息到服务器
    }

    return 0; // 程序正常退出
}
